/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package controllers;

import java.io.*;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import models.Course;
import models.CourseFile;
import models.User;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.hibernate.Session;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import service.CourseDao;
import service.HibernateUtil;
import service.PaymentDao;
import service.UserDao;

/**
 *
 * @author kjeld
 */
public class CourseFileController extends HttpServlet {

    private HibernateUtil HU = new HibernateUtil();
    private Session session = HU.openSession();
    private CourseDao dao = new CourseDao(session);
    private UserDao udao = new UserDao(session);
    private PaymentDao pdao = new PaymentDao(session);
    private String filePath;
    private String subfolder;
    private File file;
    private static final int BUFSIZE = 4096;
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        if (request.getParameter("courseID") != null) {
            long userID = 0;
            for (Cookie cookie : request.getCookies()) {
                if (cookie.getName().equals("userID")) {
                    if (cookie.getValue().length() > 0) {
                        userID = Long.parseLong(cookie.getValue());
                    }
                    break;
                }
            }
            if (userID != 0) {
                User user = udao.get(userID);
                Set<Course> courses = user.getStudentCourses();
                boolean subscribed = false;
                long courseID = Long.parseLong(request.getParameter("courseID"));
                Course userCourse = null;
                for (Course course : courses) {
                    if (course.getCourseID() == courseID) {
                        subscribed = true;
                        userCourse = course;
                        break;
                    }
                }
                if (subscribed == true) {
                    HttpSession sessie = request.getSession(true);
                    sessie.setAttribute("course", userCourse);
                    try {
                        
                            String courseName = userCourse.getName();
                            courseName = courseName.toLowerCase();
                            char[] charArray = courseName.toCharArray();
                            String folderName = "";
                            for (int i = 0; i < charArray.length; i++) {
                                char c = charArray[i];
                                if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z')) {
                                    folderName += c;
                                }
                            }
                            sessie.setAttribute("foldername", folderName);
                            filePath = folderName;
                            sessie.setAttribute("courseID", request.getParameter("courseID"));
                        
                        subfolder = "";
                        if (request.getParameter("selectedfile") != null) {
                            for (Cookie cookie : request.getCookies()) {
                                if (cookie.getName().equals("subfolder")) {
                                    subfolder = cookie.getValue();
                                }
                            }
                            if (request.getParameter("selectedfile").equals("..")) {
                                StringTokenizer subfolderArray = new StringTokenizer(subfolder, "/");
                                String removeFolder = "";
                                while (subfolderArray.hasMoreTokens()) {
                                    removeFolder = subfolderArray.nextToken();
                                    //System.out.println("subfolder= " + removeFolder);
                                }
                                subfolder = subfolder.replace("/" + removeFolder, "");

                                sessie.setAttribute("subfolder", subfolder);
                                Cookie subfolderCookie = new Cookie("subfolder", subfolder);
                                response.addCookie(subfolderCookie);
                            } else {
                                String selectedfile = request.getParameter("selectedfile");
                                StringTokenizer fileArray = new StringTokenizer(request.getParameter("selectedfile"), ".");
                                String extension = new String();
                                if (fileArray.countTokens() > 1) {
                                    while (fileArray.hasMoreTokens()) {
                                        extension = fileArray.nextToken();
                                    }
                                    String fileString = getServletContext().getRealPath("/") + "files/" + filePath + subfolder + "/" + request.getParameter("selectedfile");
                                    System.out.println("filestring: " + fileString);
                                    File file = new File(fileString);
                                    int length = 0;
                                    ServletOutputStream outStream = response.getOutputStream();
                                    ServletContext context = getServletConfig().getServletContext();
                                    String mimetype = context.getMimeType(fileString);

                                    // sets response content type
                                    if (mimetype == null) {
                                        mimetype = "application/octet-stream";
                                    }
                                    response.setContentType(mimetype);
                                    response.setContentLength((int) file.length());
                                    String fileName = (new File(fileString)).getName();
                                    System.out.println("filename: " + fileName);
                                    // sets HTTP header
                                    response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");

                                    byte[] byteBuffer = new byte[BUFSIZE];
                                    DataInputStream in = new DataInputStream(new FileInputStream(file));

                                    // reads the file's bytes and writes them to the response stream
                                    while ((in != null) && ((length = in.read(byteBuffer)) != -1)) {
                                        outStream.write(byteBuffer, 0, length);
                                    }

                                    in.close();
                                    outStream.close();
                                    System.out.println("Has extension: " + extension);
                                } else {
                                    subfolder += "/" + request.getParameter("selectedfile");
                                    sessie.setAttribute("subfolder", subfolder);
                                    Cookie subfolderCookie = new Cookie("subfolder", subfolder);
                                    response.addCookie(subfolderCookie);
                                }
                            }
                        } else {
                            sessie.setAttribute("subfolder", subfolder);
                            for (Cookie cookie : request.getCookies()) {
                                if (cookie.getName().equals("subfolder")) {
                                    cookie.setValue("");
                                    response.addCookie(cookie);
                                }
                            }
                        }
                        String root = getServletContext().getRealPath("/");
                        sessie.setAttribute("rootFolder", root + "files/");
                        File vDir = new File(root + "files/" + filePath + subfolder);
                        File[] contents = vDir.listFiles();
                        List files = new ArrayList();
                        List directories = new ArrayList();
                        for (File theFile : contents) {
                            System.out.println("Filename: " + theFile.getName());
                            if (theFile.isDirectory() == true) {
                                directories.add(theFile);
                            } else {
                                if (!theFile.getName().equals("descriptions.xml") && !theFile.getName().equals(".DS_Store") && !theFile.getName().equals("folderdescription.txt")) {
                                    files.add(theFile);
                                }
                            }
                        }
                        sessie.setAttribute("files", files);
                        sessie.setAttribute("directories", directories);
                        List<CourseFile> descriptions = readXML();
                        sessie.setAttribute("descriptions", descriptions);
                        sessie.setAttribute("folderdescription", "");
                        String folderDescription = getFolderDescription(root);
                        sessie.setAttribute("folderdescription", folderDescription);
                    } catch (Exception ex) {
                        System.out.println(ex);
                    }
                    RequestDispatcher dispatcher = request.getRequestDispatcher("/coursefiles.jsp");
                    dispatcher.forward(request, response);
                } else {
                    response.sendRedirect("/courses");
                }
            } else {
                response.sendRedirect("/index");
            }
        } else {
            response.sendRedirect("/courses");
        }
    }
    
    private String getFolderDescription(String rootPath) throws IOException {
        BufferedReader in = null;
        String description = "";
        try {
            File file = new File(rootPath + "/files/" + filePath + subfolder + "/" + "folderdescription.txt");
            if (file.exists() == true) {
                in = new BufferedReader(new FileReader(file));
                while (in.ready()) {
                    description += in.readLine() + "<br/>";
                }
                in.close();
            } else {
                return "";
            }
        } catch (FileNotFoundException ex) {
            Logger.getLogger(FileManagementController.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            try {
                in.close();
            } catch (IOException ex) {
                Logger.getLogger(FileManagementController.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return description;
    }
    
    private List<CourseFile> readXML() {
        List<CourseFile> fileDescriptions = new ArrayList();
        try {
            String root = getServletContext().getRealPath("/");
            File fXmlFile = new File(root + "/files/" + filePath + subfolder + "/descriptions.xml");
            if (fXmlFile.exists()) {
                DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
                DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
                Document doc = dBuilder.parse(fXmlFile);
                doc.getDocumentElement().normalize();

                System.out.println("Root element :" + doc.getDocumentElement().getNodeName());
                NodeList nList = doc.getElementsByTagName("FileDescription");
                System.out.println("-----------------------");
                for (int temp = 0; temp < nList.getLength(); temp++) {

                    Node nNode = nList.item(temp);
                    if (nNode.getNodeType() == Node.ELEMENT_NODE) {

                        Element eElement = (Element) nNode;
                        String filename = getTagValue("Filename", eElement);
                        String description = getTagValue("Description", eElement);
                        System.out.println("File name: " + filename);
                        System.out.println("Description: " + description);
                        
                        CourseFile courseFile = new CourseFile(filename, description);
                        fileDescriptions.add(courseFile);

                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return fileDescriptions;
    }

    private static String getTagValue(String sTag, Element eElement) {
        NodeList nlList = eElement.getElementsByTagName(sTag).item(0).getChildNodes();

        Node nValue = (Node) nlList.item(0);

        return nValue.getNodeValue();
    }

    private void writeXML(String filename, String description, String rootPath) {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
//      System.out.print("Enter number to add elements in your XML file: ");
//      String str = bf.readLine();
        int no = 2;
//      System.out.print("Enter root: ");
        String root = "FileDescriptions";
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();

        DocumentBuilder documentBuilder = null;
        try {
            documentBuilder = documentBuilderFactory.newDocumentBuilder();
        } catch (ParserConfigurationException ex) {
            Logger.getLogger(FileManagementController.class.getName()).log(Level.SEVERE, null, ex);
        }
        File file;
        file = new File(rootPath + "/files/" + filePath + subfolder + "/" + "descriptions.xml");
        Element rootElement = null;
        Document document = null;
        if (!file.exists()) {
            document = documentBuilder.newDocument();
            rootElement = document.createElement(root);
            document.appendChild(rootElement);
        } else {
            try {
                document = documentBuilder.parse(file);
                rootElement = document.getDocumentElement();
                //rootElement = (Element)document.getFirstChild();
                //rootElement = document.getDocumentElement();
            } catch (SAXException ex) {
                Logger.getLogger(FileManagementController.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IOException ex) {
                Logger.getLogger(FileManagementController.class.getName()).log(Level.SEVERE, null, ex);
            }
        }


        Element rootElement2 = document.createElement("FileDescription");


//      for (int i = 1; i <= no; i++)
//        System.out.print("Enter the element: ");
//        String element = bf.readLine();
        String element = "Filename";
        String data = filename;
        Element em = document.createElement(element);
        em.appendChild(document.createTextNode(data));
        rootElement2.appendChild(em);

        String element1 = "Description";
        String data1 = description;
        Element em1 = document.createElement(element1);
        em1.appendChild(document.createTextNode(data1));
        rootElement2.appendChild(em1);

        rootElement.appendChild(rootElement2);
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = null;
        try {
            transformer = transformerFactory.newTransformer();
        } catch (TransformerConfigurationException ex) {
            Logger.getLogger(FileManagementController.class.getName()).log(Level.SEVERE, null, ex);
        }
        DOMSource source = new DOMSource(document);

        StreamResult result = new StreamResult(new StringWriter());

        //t.setParameter(OutputKeys.INDENT, "yes");
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "5");
        try {
            transformer.transform(source, result);
        } catch (TransformerException ex) {
            Logger.getLogger(FileManagementController.class.getName()).log(Level.SEVERE, null, ex);
        }

        //writing to file
        //root + "/files/" + filePath + subfolder + "/" + fileName


        FileOutputStream fop = null;
        try {


            fop = new FileOutputStream(file);

            // if file doesnt exists, then create it
            if (!file.exists()) {
                file.createNewFile();
            }

            // get the content in bytes
            String xmlString = result.getWriter().toString();
            System.out.println(xmlString);
            byte[] contentInBytes = xmlString.getBytes();

            fop.write(contentInBytes);
            fop.flush();
            fop.close();

            System.out.println("Done");

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fop != null) {
                    fop.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws
            IOException, ServletException {
        String description = "Geen beschrijving";
        //System.out.println("request description: " + request.getParameter("description"));
        //filePath = getServletContext().getRealPath("/") + "files/";
        boolean isMultipart = ServletFileUpload.isMultipartContent(request);
        System.out.println("isMultiPart: " + isMultipart);
        if (isMultipart) {
            FileItemFactory factory = new DiskFileItemFactory();
            ServletFileUpload upload = new ServletFileUpload(factory);

            try {
                List items = upload.parseRequest(request);
                Iterator iterator = items.iterator();
                while (iterator.hasNext()) {
                    FileItem item = (FileItem) iterator.next();
                    if (!item.isFormField()) {
                        String fileName = item.getName();

                        String root = getServletContext().getRealPath("/");
                        File path = new File(root + "/files/" + filePath + subfolder);
                        if (!path.exists()) {
                            boolean status = path.mkdirs();
                        }
                        System.out.println("description: " + description);
                        writeXML(fileName, description, root);
                        File uploadedFile = new File(path + "/" + fileName);
                        System.out.println(uploadedFile.getAbsolutePath());
                        item.write(uploadedFile);
                    } else {
                        String name = item.getFieldName();
                        if(item.getString().length() > 0){
                            description = item.getString();
                        }
                        else {
                            description = "geen beschrijving";
                        }
                        //System.out.println("name: " + name + "\nvalue: " + value);
                    }
                }
            } catch (FileUploadException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //RequestDispatcher dispatcher = request.getRequestDispatcher("tutorfilemanager.jsp");
        //dispatcher.forward(request, response);
        HttpSession sessie = request.getSession(true);
        response.sendRedirect("/studentcourse/files?courseID=" + sessie.getAttribute("courseID"));
    }

}
